package com.lipaluma.xml.mapping;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;

import org.apache.commons.lang.BooleanUtils;

import com.lipaluma.field.mapper.FieldMapper;
import com.lipaluma.field.mapper.single.impl.ObjectFieldMapper;
import com.lipaluma.field.merge.FieldMergedFunction;
import com.lipaluma.xml.XmlMappingClass;
import com.lipaluma.xml.adaptor.XmlAdaptor;
import com.lipaluma.xml.merge.XmlCustomMerge;
import com.lipaluma.xml.merge.XmlFieldMerged;
import com.lipaluma.xml.merge.XmlStrategyMerge;
import com.lipaluma.xml.merge.XmlTargetMerged;
import com.lipaluma.xml.validator.XmlValidator;

@XmlRootElement(name=XmlObjectFieldMapping.MAP_OBJECT)
@XmlAccessorType(XmlAccessType.FIELD)
public class XmlObjectFieldMapping implements XmlFieldMapping, XmlMappingClass {
	public static final String MAP_OBJECT = "map-object";

	@XmlAttribute(required=true)
	private String field;
	@XmlAttribute(name="one-to-many")
	private Boolean oneToMany;
	@XmlAttribute
	private Boolean id;
	
	@XmlElements({
		@XmlElement(name=XmlStrategyMerge.FIELD_MERGED, type=XmlStrategyMerge.class),
		@XmlElement(name=XmlCustomMerge.FIELD_MERGED_CUSTOM, type=XmlCustomMerge.class)
	})
	private XmlFieldMerged fieldMerged;

	@XmlElements({
		@XmlElement(name=XmlColumnMapping.COLUMN, type=XmlColumnMapping.class),
		@XmlElement(name=XmlPathMapping.PATH, type=XmlPathMapping.class),
		@XmlElement(name=XmlMultipleColumnsMapping.MULTIPLE_COLUMNS, type=XmlMultipleColumnsMapping.class),
		@XmlElement(name=XmlMultiplePathesMapping.MULTIPLE_PATHES, type=XmlMultiplePathesMapping.class),
		@XmlElement(name=XmlObjectFieldMapping.MAP_OBJECT, type=XmlObjectFieldMapping.class)
	})
	private List<? extends XmlFieldMapping> mappings;

	@XmlElement(name=XmlTargetMerged.TARGET_MERGED)
	private XmlTargetMerged targetMergedBy;
	
	@XmlAttribute(name="target-merged")
	private Boolean targetCanBeMerged;

	@Override
	public boolean fieldMerged() {
		return fieldMerged != null;
	}

	@Override
	public Class<? extends FieldMapper> with() {
		return ObjectFieldMapper.class;
	}
	
	@Override
	public boolean isMultiple() {
		return false;
	}
	
	@Override
	public List<? extends XmlFieldMapping> getMappings() {
		if(mappings == null)
			return new ArrayList<XmlFieldMapping>();
		return mappings;
	}

	@Override
	public String getField() {
		return field;
	}
	@Override
	public boolean isOneToMany() {
		return BooleanUtils.toBoolean(oneToMany);
	}
	@Override
	public boolean isId() {
		return BooleanUtils.toBoolean(id);
	}

	@Override
	public boolean isTargetCanBeMerged() {
		return BooleanUtils.toBoolean(targetCanBeMerged) || targetMergedBy != null;
	}

	@Override
	public XmlTargetMerged targetMergedBy() {
		return targetMergedBy;
	}
	
	@Override
	public FieldMergedFunction mergedBy() {
		if(fieldMerged == null)
			return new FieldMergedFunction(null);
		return new FieldMergedFunction(fieldMerged.getAlgorithm(), fieldMerged.getParams());
	}

	@Override
	public String getPattern() {
		return null;
	}
	@Override
	public String getLocale() {
		return null;
	}
	@Override
	public boolean isRequired() {
		return false;
	}
	@Override
	public boolean isEachValueRequired() {
		return false;
	}
	@Override
	public boolean isTrim() {
		return false;
	}
	@Override
	public String getSeparator() {
		return null;
	}
	@Override
	public boolean isKeepAll() {
		return false;
	}
	@Override
	public String[] getFalseValues() {
		return null;
	}
	@Override
	public String[] getTrueValues() {
		return null;
	}
	@Override
	public List<? extends XmlAdaptor> getAdaptors() {
		return null;
	}
	@Override
	public List<? extends XmlValidator> getValidators() {
		return null;
	}
	@Override
	public List<? extends XmlAdaptor> getAdaptorsOnEachValue() {
		return null;
	}
	@Override
	public List<? extends XmlValidator> getValidatorsOnEachValue() {
		return null;
	}
}
